package com.tj.collection.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fqgj.base.services.redis.RedisClient;
import com.fqgj.common.api.Page;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.DateUtil;
import com.fqgj.common.utils.StringUtils;
import com.fqgj.exception.common.ApplicationException;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.tj.collection.db.dao.*;
import com.tj.collection.db.entity.AiNoOverdueOutboundEntity;
import com.tj.collection.db.entity.AiOverdueOutboundEntity;
import com.tj.collection.db.entity.ClOutboundBatchEntity;
import com.tj.collection.db.entity.ClOutboundDetailEntity;
import com.tj.collection.db.entity.business.ClOutboundEntity;
import com.tj.collection.enums.AICallStatusEnum;
import com.tj.collection.enums.OutboundBatchStatusEnum;
import com.tj.collection.enums.OutboundDetailStatusEnum;
import com.tj.collection.integration.MessageIntegrationService;
import com.tj.collection.service.third.OutboundService;
import com.tj.collection.utils.ConfigUtil;
import com.tj.collection.utils.TextFormatUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: pavan
 * Date: 2020/2/25
 * Time: 上午11:04
 */
@Service
public class ClOutboundService {

    private static final Log LOGGER = LogFactory.getLog(ClOutboundService.class);

    @Autowired
    private ConfigUtil configUtil;
    @Autowired
    private RedisClient redisClient;
    @Autowired
    private ClOutboundBatchDao clOutboundBatchDao;
    @Autowired
    private ClOutboundDetailDao clOutboundDetailDao;
    @Autowired
    private OutboundService outboundService;
    @Autowired
    private ClQueryDao clQueryDao;
    @Autowired
    private AiNoOverdueOutboundDao aiNoOverdueOutboundDao;
    @Autowired
    private ClReceiverDao clReceiverDao;
    @Autowired
    private ClReceiverDetailDao clReceiverDetailDao;
    @Autowired
    private MessageIntegrationService messageIntegrationService;
    @Autowired
    private AiOverdueOutboundDao aiOverdueOutboundDao;
    @Autowired
    private AllocationService allocationService;

    public Integer countOutbound(String merchantCode, int overdueDays) {
        return clQueryDao.countOutboundList(merchantCode, overdueDays);
    }

    /**
     * 一天只能触发一次
     */
    public void call(String merchantCode, int overdueDays, int limit) {
        this.addCallTask(merchantCode, overdueDays, "open_api", new Page(limit));
    }

    /**
     * 添加任务
     *
     * @param merchantCode
     * @param overdueDays
     */
    public int addCallTask(String merchantCode, Integer overdueDays, String channelSource, Page page) {
        String batch = "D_" + merchantCode + "_" + overdueDays + "_" + DateUtil.getDate(new Date(), "yyyyMMddHHmmss");

        LOGGER.info("addCallTask,添加任务开始,merchantCode:{},overdueDays:{},batch:{}", merchantCode, overdueDays, batch);
        Integer SIZE = 1000;

        List<ClOutboundEntity> clOutboundEntityList = clQueryDao.selectOutboundList(merchantCode, overdueDays, channelSource, page == null ? new Page(2000) : page);
        if (CollectionUtils.isEmpty(clOutboundEntityList)) {
            LOGGER.info("没有需要呼叫的订单,overdueDays:{},batch:{}", overdueDays, batch);
            return 0;
        }

        StringBuffer mobileList = new StringBuffer();
        String batchName = null;
        Date callDateD = new Date();
        String callDate = DateUtil.getDate(callDateD, "yyyyMMdd");

        List<List<ClOutboundEntity>> list = new ArrayList<>();//1000条一组
        List<ClOutboundEntity> listItem = new ArrayList<>();

        LOGGER.info("调试日志,size:{},clOutboundEntityList:{}", clOutboundEntityList.size(), JSON.toJSONString(clOutboundEntityList));

        //分成1000条一组
        for (int i = 0; i < clOutboundEntityList.size(); i++) {
            ClOutboundEntity entity = clOutboundEntityList.get(i);
            listItem.add(entity);
            if (listItem.size() == SIZE) {
                list.add(listItem);
                LOGGER.info("调试日志,分包,size:{},listItem:{}", listItem.size(), JSON.toJSONString(listItem));
                listItem = new ArrayList<>();
            }
        }
        if (listItem.size() > 0 && listItem.size() < SIZE) {
            list.add(listItem);
            LOGGER.info("调试日志,分包最后一包,size:{},listItem:{}", listItem.size(), JSON.toJSONString(listItem));
        }
        LOGGER.info("调试日志,分包数据,list:{}", JSON.toJSONString(list));

        for (int i = 0; i < list.size(); i++) {
            List<ClOutboundEntity> entityList = list.get(i);

            mobileList = new StringBuffer();
            batchName = batch + "_" + (i % SIZE);

            LOGGER.info("调试日志,INDEX={}处理,batchName:{},size:{},entityList:{}", i, batchName, entityList.size(), JSON.toJSONString(entityList));

            try {
                JSONObject jsonObject = configUtil.getOutboundParams();
                String botenceId = jsonObject.getJSONObject(merchantCode + (StringUtils.isEmpty(channelSource) ? "" : channelSource)).getString("botenceId");
                if (StringUtils.isEmpty(botenceId)) {
                    throw new ApplicationException("模板为空");
                }

                for (ClOutboundEntity entity : entityList) {
                    if (mobileList.length() == 0) {
                        mobileList.append(TextFormatUtil.format("{mobile}^dueday-money^{repaymentDate}-{amount}", entity.getMobile(), DateUtil.getDate(entity.getRepaymentDate(), "yyyy/MM/dd"), entity.getRepaymentCapital().setScale(0, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString()));
                    } else {
                        mobileList.append(TextFormatUtil.format("|{mobile}^dueday-money^{repaymentDate}-{amount}", entity.getMobile(), DateUtil.getDate(entity.getRepaymentDate(), "yyyy/MM/dd"), entity.getRepaymentCapital().setScale(0, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString()));
                    }
                    //明细入库
                    ClOutboundDetailEntity clOutboundDetailEntity = new ClOutboundDetailEntity()
                            .setBatchNo(batchName)
                            .setTradeNo(entity.getTradeNo())
                            .setMobile(entity.getMobile())
                            .setStatus(OutboundDetailStatusEnum.UN_CALL.getStatus())
                            .setAttach("dueday-money")
                            .setParams(TextFormatUtil.format("{repaymentDate}-{amount}", DateUtil.getDate(entity.getRepaymentDate(), "yyyy/MM/dd"), entity.getRepaymentCapital().setScale(0, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString()));
                    clOutboundDetailDao.insert(clOutboundDetailEntity);
                }

                //批次入库
                ClOutboundBatchEntity clOutboundBatchEntity = new ClOutboundBatchEntity();
                clOutboundBatchEntity.setBatchNo(batchName);
                clOutboundBatchEntity.setType("D" + overdueDays + "外呼");
                clOutboundBatchEntity.setCallDate(callDateD);
                clOutboundBatchEntity.setBotenceId(botenceId);
                clOutboundBatchEntity.setLineIds(jsonObject.getString("lineIds"));
                clOutboundBatchEntity.setStatus(OutboundBatchStatusEnum.UN_SUBMIT.getStatus());

                clOutboundBatchEntity = clOutboundBatchDao.insert(clOutboundBatchEntity);
                //调用三方
                if (mobileList != null && mobileList.length() > 0) {
                    if (configUtil.getOutboundSwitch()) {
                        if (configUtil.isServerTest() && !configUtil.getTestServiceOutboundAllow()) {
                            LOGGER.info("测试环境不添加拨打任务,只打印日志,batchName:{},callDate:{},mobileList:{}", batchName, callDate, mobileList.toString());
                        } else {
                            String result = outboundService.addPlan(batchName, callDate, mobileList.toString(), botenceId, null);
                            LOGGER.info("外呼功能调用三方结果,batchName:{},callDate:{},mobileList:{},result:{}", batchName, callDate, mobileList.toString(), result);
                        }
                    } else {
                        LOGGER.info("外呼功能关闭,只打印日志,batchName:{},callDate:{},mobileList:{}", batchName, callDate, mobileList.toString());
                    }
                    //更新状态为提交成功
                    ClOutboundBatchEntity batchEntity2 = new ClOutboundBatchEntity();
                    batchEntity2.setId(clOutboundBatchEntity.getId());
                    batchEntity2.setStatus(OutboundBatchStatusEnum.SUBMITTED.getStatus());
                    clOutboundBatchDao.updateByPrimaryKey(batchEntity2);
                }
            } catch (Exception e) {
                LOGGER.error("调用外呼接口失败,batchName:{}", batchName, e);
            }
        }
        LOGGER.info("addCallTask,添加任务结束,overdueDays:{},batch:{}", overdueDays, batch);
        return clOutboundEntityList.size();
    }

    /**
     * 供loanbee调用
     *
     * @param merchantCode
     * @param entityList
     * @param batchName
     */
    public void doCall(String merchantCode, List<ClOutboundEntity> entityList, String batchName) {
        StringBuffer mobileList = new StringBuffer();

        LOGGER.info("调试日志,INDEX={}处理,batchName:{},size:{},entityList:{}", 0, batchName, entityList.size(), JSON.toJSONString(entityList));

        Date callDateD = new Date();
        String callDate = DateUtil.getDate(callDateD, "yyyyMMdd");

        try {
            JSONObject jsonObject = configUtil.getOutboundParams();
            String botenceId = jsonObject.getJSONObject(merchantCode + "").getString("botenceId");
            if (StringUtils.isEmpty(botenceId)) {
                throw new ApplicationException("模板为空");
            }

            for (ClOutboundEntity entity : entityList) {
                if (mobileList.length() == 0) {
                    mobileList.append(TextFormatUtil.format("{mobile}^dueday-money^{repaymentDate}-{amount}", entity.getMobile(), DateUtil.getDate(entity.getRepaymentDate(), "yyyy/MM/dd"), entity.getRepaymentCapital().setScale(0, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString()));
                } else {
                    mobileList.append(TextFormatUtil.format("|{mobile}^dueday-money^{repaymentDate}-{amount}", entity.getMobile(), DateUtil.getDate(entity.getRepaymentDate(), "yyyy/MM/dd"), entity.getRepaymentCapital().setScale(0, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString()));
                }
                //明细入库
                ClOutboundDetailEntity clOutboundDetailEntity = new ClOutboundDetailEntity()
                        .setBatchNo(batchName)
                        .setTradeNo(entity.getTradeNo())
                        .setMobile(entity.getMobile())
                        .setStatus(OutboundDetailStatusEnum.UN_CALL.getStatus())
                        .setAttach("dueday-money")
                        .setParams(TextFormatUtil.format("{repaymentDate}-{amount}", DateUtil.getDate(entity.getRepaymentDate(), "yyyy/MM/dd"), entity.getRepaymentCapital().setScale(0, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString()));
                clOutboundDetailDao.insert(clOutboundDetailEntity);
            }

            //批次入库
            ClOutboundBatchEntity clOutboundBatchEntity = new ClOutboundBatchEntity();
            clOutboundBatchEntity.setBatchNo(batchName);
            clOutboundBatchEntity.setType("D" + 0 + "外呼");
            clOutboundBatchEntity.setCallDate(callDateD);
            clOutboundBatchEntity.setBotenceId(botenceId);
            clOutboundBatchEntity.setLineIds(jsonObject.getString("lineIds"));
            clOutboundBatchEntity.setStatus(OutboundBatchStatusEnum.UN_SUBMIT.getStatus());

            clOutboundBatchEntity = clOutboundBatchDao.insert(clOutboundBatchEntity);
            //调用三方
            if (mobileList != null && mobileList.length() > 0) {
                if (configUtil.getOutboundSwitch()) {
                    if (configUtil.isServerTest() && !configUtil.getTestServiceOutboundAllow()) {
                        LOGGER.info("测试环境不添加拨打任务,只打印日志,batchName:{},callDate:{},mobileList:{}", batchName, callDate, mobileList.toString());
                    } else {
                        String result = outboundService.addPlan(batchName, callDate, mobileList.toString(), botenceId, null);
                        LOGGER.info("外呼功能调用三方结果,batchName:{},callDate:{},mobileList:{},result:{}", batchName, callDate, mobileList.toString(), result);
                    }
                } else {
                    LOGGER.info("外呼功能关闭,只打印日志,batchName:{},callDate:{},mobileList:{}", batchName, callDate, mobileList.toString());
                }
                //更新状态为提交成功
                ClOutboundBatchEntity batchEntity2 = new ClOutboundBatchEntity();
                batchEntity2.setId(clOutboundBatchEntity.getId());
                batchEntity2.setStatus(OutboundBatchStatusEnum.SUBMITTED.getStatus());
                clOutboundBatchDao.updateByPrimaryKey(batchEntity2);
            }
        } catch (Exception e) {
            LOGGER.error("调用外呼接口失败,batchName:{}", batchName, e);
        }
    }

    /**
     * 无逾期用户电话沟通
     */
    public void noOverdueCall() {
        LOGGER.info("无逾期AI电话任务开始。。。。");
        String today = DateUtil.getDate("yyyyMMdd");
        Map<String, Object> param = new HashMap<String, Object>() {{
            put("deleted", 0);
            put("callStatus", 0);
        }};

        try {
            List<AiNoOverdueOutboundEntity> entities = aiNoOverdueOutboundDao.getEntity(new Page(1000, 1));
            if (CollectionUtils.isEmpty(entities)) {
                LOGGER.info("没有符合条件的用户。。。");
                return;
            }
            String batchNo = System.currentTimeMillis() + "_AI_CALL";

            StringBuffer stringBuffer = new StringBuffer();
            //获取手机号
            entities.forEach(e -> stringBuffer.append(e.getMobile()).append("|"));

            Boolean resp = outboundService.noOverdueCall(batchNo, today, stringBuffer.substring(0, stringBuffer.length() - 1),
                    "20200918221163523204466416_en", null,
                    "/collection/outbound/plan/noOverdueCall/callBackBatch",
                    "/collection/outbound/plan/noOverdueCall/callBack");

            if (resp) {
                for (AiNoOverdueOutboundEntity entity : entities) {
                    entity.setBatchNo(batchNo);
                    entity.setCallStatus(AICallStatusEnum.CALL_JOB_SUCCESS.getCode());
                    aiNoOverdueOutboundDao.updateByPrimaryKey(entity);
                }
            }

        } catch (Exception e) {
            LOGGER.error("调用外呼接口失败...");
        }

    }

    /**
     * 无逾期用户电话沟通回调发送短信
     */
    public void noOverdueCallBack(JSONObject request) {
//        LOGGER.info("接收单条回调信息,request:{}", request.toJSONString());
//
//        Integer code = request.getInteger("code");
//        if (code == null || code != 0) {
//            throw new ApplicationException("返回参数校验失败校验失败");
//        }
//
//        try {
//            JSONObject bodyObj = request.getJSONObject("body");
//            Integer billSec = bodyObj.getInteger("billSec");
//            if (null == billSec || billSec == 0) {
//                LOGGER.info("--------------- 通话未接通 不发送短信 。。。。。");
//                return;
//            }
//
//            String phone = bodyObj.getString("phone");
//            if (StringUtils.isEmpty(phone)) {
//                phone = bodyObj.getString("phoneNo");
//            }
//            LOGGER.info("---------------- 回调信息获取phone:{}", phone);
//            if (StringUtils.isNotEmpty(phone)) {
//                String userCode = "";
//                aiNoOverdueOutboundDao.updateStatus(phone, AICallStatusEnum.CALL_SUCCESS.getCode());
//
//                //TODO userCode
//                userCode = "";
//
//                LOGGER.info("---------------- 回调信息获取user:{}", JSON.toJSONString(userCode));
//                SingleSmsSendRequestRO requestRO = new SingleSmsSendRequestRO();
//                requestRO.setUserCode(userCode);
//                requestRO.setPhone(phone);
//                requestRO.setAppId(AppEnum.JYD.getId());
//                requestRO.setBizCode("CASHMAMA_1001");
//                requestRO.setReplaceParam(new HashMap<>());
//                try {
//                    LOGGER.info("---------------- 回调信息发短信开始");
//                    messageIntegrationService.send(requestRO);
//                    aiNoOverdueOutboundDao.updateStatus(phone, AICallStatusEnum.MSG_SUCCESS.getCode());
//                    LOGGER.info("---------------- 回调信息发短信结束");
//                } catch (Exception e) {
//                    e.printStackTrace();
//                    LOGGER.error("回掉短信发送失败");
//                }
//
//            } else {
//                aiNoOverdueOutboundDao.updateStatus(phone, AICallStatusEnum.CALL_FAIL.getCode());
//            }
//
//        } catch (Exception e) {
//            e.printStackTrace();
//            LOGGER.error("回单信息处理失败");
//        }
    }

    public void overdueCall(int min, int max, String code, int dayNum) {
        LOGGER.info("---------------逾期催收电话开始------------------");
        String today = DateUtil.getDate("yyyyMMdd");
        try {
            List<AiOverdueOutboundEntity> entities = aiOverdueOutboundDao.getOverdueOutboundByDays(min, max, code, dayNum);
            if (CollectionUtils.isEmpty(entities)) {
                LOGGER.info("无相关逾期订单~~~~~~~~~~~~minDay:{},maxDay:{},merChantCode:{}", min, max, code);
                return;
            }
            String batchNo = System.currentTimeMillis() + "_AI_OVERDUE_CALL";

            StringBuffer stringBuffer = new StringBuffer();
            //获取手机号
            entities.forEach(e -> stringBuffer.append(TextFormatUtil.format("{mobile}^dueday-money^{repaymentDate}-{amount}|",
                    e.getMobile(),
                    DateUtil.getDate(e.getRepamentDate(), "yyyy/MM/dd"),
                    e.getAmount().setScale(0, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString())));

            Boolean resp = outboundService.noOverdueCall(batchNo, today, stringBuffer.substring(0, stringBuffer.length() - 1),
                    "20200219106697945194455285_en", null,
                    "/collection/outbound/plan/noOverdueCall/callBackBatch",
                    "/collection/outbound/plan/overdueCall/callBack");

            if (resp) {
                for (AiOverdueOutboundEntity entity : entities) {
                    entity.setBatchNo(batchNo);
                    entity.setStatus(AICallStatusEnum.CALL_JOB_SUCCESS.getCode());
                    aiOverdueOutboundDao.updateByPrimaryKey(entity);
                }
            }
        } catch (Exception e) {
            LOGGER.error("调用外呼接口失败...");
        }
    }

    /**
     * 逾期用户电话沟通回调
     */
    public void overdueCallBack(JSONObject request) {
        LOGGER.info("逾期电话催收,单条回调信息,request:{}", request.toJSONString());

        Integer code = request.getInteger("code");
        if (code == null || code != 0) {
            throw new ApplicationException("返回参数校验失败校验失败");
        }

        try {
            JSONObject bodyObj = request.getJSONObject("body");
            Integer billSec = bodyObj.getInteger("billSec");
            String accurateIntent = bodyObj.getString("accurateIntent");
            LOGGER.info("billSec:{}", billSec);

            String phone = bodyObj.getString("phone");
            if (StringUtils.isEmpty(phone)) {
                phone = bodyObj.getString("phoneNo");
            }
            LOGGER.info("phone:{}", phone);

            if (billSec > 0) {
                LOGGER.info("call success billSec:{}", billSec);
                allocationService.updateActiveReceiverByLogin(phone, "A", "2");
                aiOverdueOutboundDao.updateAiOverdueStatus(phone, AICallStatusEnum.CALL_SUCCESS.getCode());
            } else {
                LOGGER.info("call fail billSec:{}", billSec);
                aiOverdueOutboundDao.updateAiOverdueStatus(phone, AICallStatusEnum.CALL_FAIL.getCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error("回单信息处理失败");
        }
    }

}
